//------------------------------------------------------------------------------
// The confidential and proprietary information contained in this file may
// only be used by a person authorised under and to the extent permitted
// by a subsisting licensing agreement from ARM Limited.
//
//            (C) COPYRIGHT 2008-2012 ARM Limited.
//                ALL RIGHTS RESERVED
//
// This entire notice must be reproduced on all copies of this file
// and copies of this file may only be made by a person if such person is
// permitted to do so under the terms of a subsisting license agreement
// from ARM Limited.
//------------------------------------------------------------------------------
// Version and Release Control Information:
//
// File Revision       : 130657
// File Date           :  2012-05-28 17:35:55 +0100 (Mon, 28 May 2012)
// Release Information : PL401-r0p1-00eac0
//------------------------------------------------------------------------------
// Purpose : This module is responsible for removing extra Responses from the B
//           channel
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//
//  Config :
//           o  Outstanding write responses  = 1
//
//------------------------------------------------------------------------------
module nic400_ib_sram_slv_axi4_ib_upsize_wr_resp_block_ysyx_rv32
  (
  //Inputs
  bvalid_m,
  bready_s,
  bresp_m,
  bid_m,

  bchannel_ready,

  //Inputs
  bchannel_valid,
  bchannel_data,

  //Outputs
  bvalid_s,
  bready_m,
  bid_s,
  bresp_s,

  aclk,
  aresetn
  );

`include "nic400_ib_sram_slv_axi4_ib_defs_ysyx_rv32.v"

  //System
  input                   aclk;
  input                   aresetn;

  // AWID
  output                  bchannel_ready;   //Used to stop the AW when response Queue is full

  // BCHANNEL outputs
  output                  bvalid_s;          //BVALID being sent to narrow bus
  output                  bready_m;          //BREADY being sent onto wide bus
  output [3:0]            bid_s;             //BID being sent
  output [1:0]            bresp_s;           //BRESP being sent

  //BCHANNEL inputs
  input                   bvalid_m;
  input                   bready_s;
  input [3:0]             bid_m;
  input [1:0]             bresp_m;

  //Control inputs
  input                   bchannel_valid;
  input [4:0]             bchannel_data;

  //------------------------------------------------------------------------
  // Wires
  //------------------------------------------------------------------------

   wire                   match_bus;
   wire                   hazard_bus;

   wire                   valid_bus;
   wire                   match;              //a match has occured
   wire                   hazard;             //hazard detected

   wire                   bready_m_i;
   wire                   bhndshk;

   wire                   push_slice;
   wire                   pop_slice;          //push and pop signals for the CAM Slices
   wire                   update;
   

   wire [3:0]             awid;
   wire                   n_response;
   wire                   next_bchannel_ready;
   
   wire [1:0]             bresp_out_0;
    
  //------------------------------------------------------------------------
  // Regs
  //------------------------------------------------------------------------

   reg                    hazard_pointer;
   reg                    match_pointer;

   reg                    store;

   reg                    bchannel_ready_i;  

  //------------------------------------------------------------------------
  // Decode bchannel Data
  //------------------------------------------------------------------------

   assign awid = bchannel_data[4:1];
   assign n_response = bchannel_data[0];
  //------------------------------------------------------------------------
  // Main Code
  //------------------------------------------------------------------------

   //match
   assign match = match_bus;

   //hazard
   assign hazard = hazard_bus;

   //Not ready if all Slices are full (unless one is about to be emptied)
   //A slot will be emptied on match and update
   assign next_bchannel_ready = ~((valid_bus | (store & {1{push_slice}}))) || (pop_slice);

   //Registered bchannel ready
   always @(posedge aclk or negedge aresetn)
    begin : bchannel_seq
      if (!aresetn)
         bchannel_ready_i <= 1'b0;
      else
         bchannel_ready_i <= next_bchannel_ready;
    end //bchannel_seq

   assign bchannel_ready = bchannel_ready_i;
   //store decode Logic
   always @(valid_bus or match_bus)
     begin : store_decode
        if (!valid_bus)
           store = 1'b1;
        else
            store = match_bus;
      end // store_decode

    //Distribute the number of the Slice reporting a hazard
   always @(hazard_bus)
     begin : hazard_num_distibution
       case (hazard_bus)
          1'b0 : hazard_pointer = 1'b0;
           1'd1 : hazard_pointer = 1'd0;
         default : hazard_pointer = 1'bx;
       endcase
     end

    //Distribute the number of the Slice reporting a match
   always @(match_bus)
     begin : match_num_distibution
       case (match_bus)
          1'b0 : match_pointer = 1'b0;
           1'd1 : match_pointer = 1'd0;
         default : match_pointer = 1'bx;
       endcase
     end

    //Indicate that that data is being written form the AWChannel
    assign push_slice = bchannel_ready_i && bchannel_valid;

    //Indicate incoming on B channel
    assign bhndshk = bvalid_m && bready_m_i;
    assign update = bhndshk;
    assign pop_slice = update && match;

   //------------------------------------------------------------------------
   // B channel Control
   //------------------------------------------------------------------------

    //Output BREADY
    assign bready_m_i = bvalid_m && (bready_s || ~match);
    assign bready_m   = bready_m_i;
    //bchannel outputs
    assign bid_s = bid_m;
    assign bresp_s = (bresp_m
                      |  bresp_out_0 );

    //BVALID is only sent if a match is detected
    assign bvalid_s = (bvalid_m && match);


   //------------------------------------------------------------------------
   // CAM SLices
   //------------------------------------------------------------------------

    
     //Cam Slice number 0 //

     nic400_ib_sram_slv_axi4_ib_upsize_resp_cam_slice_ysyx_rv32 u_upsize_resp_cam_slice_0
     (
         // global signals
        .aresetn              (aresetn),
        .aclk                 (aclk),

        // ID inputs (to all slices)
        .matchid              (bid_m),
        .hazardid             (awid),

        //Control Signals
        .store                (store),
        .push_slice           (push_slice),
        .pop_slice            (pop_slice),
        .update               (update),
        .match_pointer        (match_pointer),

        .hazard_in            (hazard),
        .hazard_pointer       (hazard_pointer),

        .n_response           (n_response),
        .bresp_in             (bresp_m),

        //Outputs
        .hazard               (hazard_bus),
        .match                (match_bus),
        .valid                (valid_bus),
        .bresp_out            (bresp_out_0)
     );
     


`ifdef ARM_ASSERT_ON

   //------------------------------------------------------------------------
   // OVL_ASSERT: Check that only one Slice ever matches
   //------------------------------------------------------------------------
   // If more than one slot matches the hazard detection logic has gone wrong
   //------------------------------------------------------------------------

   // OVL_ASSERT_RTL
  assert_never_unknown #(0,1,"B Channel Slice match has gone wrong")
  ovl_single_ID_match
    (
     .clk              (aclk),
     .reset_n          (aresetn),
     .qualifier        (match_bus),
     .test_expr        (bvalid_m)
     );
   // OVL_ASSERT_END

   //------------------------------------------------------------------------
   // OVL_ASSERT: Check that only one Slice ever reports a hazard
   //------------------------------------------------------------------------
   // If more than one slot matches the last detection logic has gone wrong
   //------------------------------------------------------------------------

   // OVL_ASSERT_RTL
  assert_never_unknown #(0,1,"B Channel Slice hazard has gone wrong")
  ovl_single_hazard
    (
     .clk              (aclk),
     .reset_n          (aresetn),
     .qualifier        (hazard_bus),
     .test_expr        (bchannel_valid)
     );
   // OVL_ASSERT_END

   //------------------------------------------------------------------------
   // OVL_ASSERT: Check that there is never an incoming transaction when there are
   //             no valid slices
   //------------------------------------------------------------------------
   // If no slices are valid then something has gone wrong
   //------------------------------------------------------------------------

   // OVL_ASSERT_RTL
  assert_never #(0,0,"No slices are valid and there is an incoming transaction")
  ovl_bslice_none_valid
    (
     .clk              (aclk),
     .reset_n          (aresetn),
     .test_expr        (~|valid_bus && bvalid_m)
     );
   // OVL_ASSERT_END

   //------------------------------------------------------------------------
   // OVL_ASSERT: Check that if an incoming transaction has an ex_okay resp
   //             then it must match a slice .. and be output as an ex_okay
   //------------------------------------------------------------------------
   // If no slices are valid then something has gone wrong
   //------------------------------------------------------------------------

   // OVL_ASSERT_RTL
  assert_implication #(0,0,"ex_okay reponses lost")
  ovl_exokay_lost
    (
     .clk              (aclk),
     .reset_n          (aresetn),
     .antecedent_expr  (bvalid_m && bresp_m == 2'b01),
     .consequent_expr  (match && bresp_s == 2'b01)
     );
   // OVL_ASSERT_END

   //------------------------------------------------------------------------
   // OVL_ASSERT: This block has a normal V/R handshake input. However, in all
   // NIC400 configurations. Valid should only ever asserted when ready is.
   //------------------------------------------------------------------------
   // Handshake error
   //------------------------------------------------------------------------

   // OVL_ASSERT_RTL
  assert_implication #(0,0,"B Channel HndShk Error")
  ovl_input_hndshk_error
    (
     .clk              (aclk),
     .reset_n          (aresetn),
     .antecedent_expr  (bchannel_valid),
     .consequent_expr  (bchannel_ready_i)
     );
   // OVL_ASSERT_END

   //------------------------------------------------------------------------
   // OVL_ASSERT: HandShk tracking
   //------------------------------------------------------------------------
   // Check for handshake under/overflow
   //------------------------------------------------------------------------

   // OVL_ASSERT_RTL
   assert_fifo_index #(0, 1, 1, 1, 0,"ERROR, BChannel Look-Up under or overflowed")
      ovl_bchannel_fifo_index
         (
           .clk       (aclk),
           .reset_n   (aresetn),
           .push      (bchannel_ready_i && bchannel_valid),
           .pop       (bvalid_s && bready_s)
         );
   // OVL_ASSERT_END



`endif

`include "nic400_ib_sram_slv_axi4_ib_undefs_ysyx_rv32.v"

endmodule
